zynqmp: pm: Implement IOCTL APIs for remoteproc
authorRajan Vaja <[email protected]>
Wed, 17 Jan 2018 10:39:23 +0000 (02:39 -0800)
committerJolly Shah <[email protected]>
Thu, 15 Mar 2018 17:23:31 +0000 (10:23 -0700)
Implement ioctl APIs which uses MMIO operations
to control RPU operations. Below IOCTLs are supported
in this patch:
  * Get RPU operation mode
  * Set RPU operation mode
  * Configure RPU boot address (OCM/TCM)
  * Configure TCM combined mode

Signed-off-by: Rajan Vaja <[email protected]>
Signed-off-by: Jolly Shah <[email protected]>
plat/xilinx/zynqmp/platform.mk
plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c [new file with mode: 0644]
plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h [new file with mode: 0644]
plat/xilinx/zynqmp/pm_service/pm_api_sys.c
plat/xilinx/zynqmp/pm_service/pm_api_sys.h
plat/xilinx/zynqmp/pm_service/pm_defs.h
plat/xilinx/zynqmp/pm_service/pm_svc_main.c
plat/xilinx/zynqmp/zynqmp_def.h

index cefb73a656b977ef136644db901a1184cfc69ab1..2abcd288ce9bef0f92736c77e15a510b42056c4c 100644 (file)
@@ -78,6 +78,7 @@ BL31_SOURCES          +=      drivers/arm/cci/cci.c                           \
                                plat/xilinx/zynqmp/pm_service/pm_svc_main.c     \
                                plat/xilinx/zynqmp/pm_service/pm_api_sys.c      \
                                plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c  \
+                               plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c    \
                                plat/xilinx/zynqmp/pm_service/pm_ipi.c          \
                                plat/xilinx/zynqmp/pm_service/pm_client.c       \
                                plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
new file mode 100644 (file)
index 0000000..6f94f42
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for ioctl.
+ */
+
+#include <arch_helpers.h>
+#include <delay_timer.h>
+#include <mmio.h>
+#include <platform.h>
+#include "pm_api_ioctl.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+#include "../zynqmp_def.h"
+
+/**
+ * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode
+ * @mode       Buffer to store value of oper mode(Split/Lock-step)
+ *
+ * This function provides current configured RPU operational mode.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode)
+{
+       unsigned int val;
+
+       val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+       val &= ZYNQMP_SLSPLIT_MASK;
+       if (val)
+               *mode = PM_RPU_MODE_SPLIT;
+       else
+               *mode = PM_RPU_MODE_LOCKSTEP;
+
+       return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode
+ * @mode       Value to set for oper mode(Split/Lock-step)
+ *
+ * This function configures RPU operational mode(Split/Lock-step).
+ * It also sets TCM combined mode in RPU lock-step and TCM non-combined
+ * mode for RPU split mode. In case of Lock step mode, RPU1's output is
+ * clamped.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode)
+{
+       unsigned int val;
+
+       if (mmio_read_32(CRL_APB_RST_LPD_TOP) && CRL_APB_RPU_AMBA_RESET)
+               return PM_RET_ERROR_ACCESS;
+
+       val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+
+       if (mode == PM_RPU_MODE_SPLIT) {
+               val |= ZYNQMP_SLSPLIT_MASK;
+               val &= ~ZYNQMP_TCM_COMB_MASK;
+               val &= ~ZYNQMP_SLCLAMP_MASK;
+       } else if (mode == PM_RPU_MODE_LOCKSTEP) {
+               val &= ~ZYNQMP_SLSPLIT_MASK;
+               val |= ZYNQMP_TCM_COMB_MASK;
+               val |= ZYNQMP_SLCLAMP_MASK;
+       } else {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
+
+       return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_config_boot_addr() - Configure RPU boot address
+ * @nid                Node ID of RPU
+ * @value      Value to set for boot address (TCM/OCM)
+ *
+ * This function configures RPU boot address(memory).
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid,
+                                                   unsigned int value)
+{
+       unsigned int rpu_cfg_addr, val;
+
+       if (nid == NODE_RPU_0)
+               rpu_cfg_addr = ZYNQMP_RPU0_CFG;
+       else if (nid == NODE_RPU_1)
+               rpu_cfg_addr = ZYNQMP_RPU1_CFG;
+       else
+               return PM_RET_ERROR_ARGS;
+
+       val = mmio_read_32(rpu_cfg_addr);
+
+       if (value == PM_RPU_BOOTMEM_LOVEC)
+               val &= ~ZYNQMP_VINITHI_MASK;
+       else if (value == PM_RPU_BOOTMEM_HIVEC)
+               val |= ZYNQMP_VINITHI_MASK;
+       else
+               return PM_RET_ERROR_ARGS;
+
+       mmio_write_32(rpu_cfg_addr, val);
+
+       return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_config_tcm_comb() - Configure TCM combined mode
+ * @value      Value to set (Split/Combined)
+ *
+ * This function configures TCM to be in split mode or combined
+ * mode.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value)
+{
+       unsigned int val;
+
+       val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+
+       if (value == PM_RPU_TCM_SPLIT)
+               val &= ~ZYNQMP_TCM_COMB_MASK;
+       else if (value == PM_RPU_TCM_COMB)
+               val |= ZYNQMP_TCM_COMB_MASK;
+       else
+               return PM_RET_ERROR_ARGS;
+
+       mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
+
+       return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_ioctl() -  PM IOCTL API for device control and configs
+ * @node_id    Node ID of the device
+ * @ioctl_id   ID of the requested IOCTL
+ * @arg1       Argument 1 to requested IOCTL call
+ * @arg2       Argument 2 to requested IOCTL call
+ * @value      Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
+                               unsigned int ioctl_id,
+                               unsigned int arg1,
+                               unsigned int arg2,
+                               unsigned int *value)
+{
+       int ret;
+
+       switch (ioctl_id) {
+       case IOCTL_GET_RPU_OPER_MODE:
+               ret = pm_ioctl_get_rpu_oper_mode(value);
+               break;
+       case IOCTL_SET_RPU_OPER_MODE:
+               ret = pm_ioctl_set_rpu_oper_mode(arg1);
+               break;
+       case IOCTL_RPU_BOOT_ADDR_CONFIG:
+               ret = pm_ioctl_config_boot_addr(nid, arg1);
+               break;
+       case IOCTL_TCM_COMB_CONFIG:
+               ret = pm_ioctl_config_tcm_comb(arg1);
+               break;
+       default:
+               ret = PM_RET_ERROR_NOTSUPPORTED;
+       }
+
+       return ret;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
new file mode 100644 (file)
index 0000000..9dae69f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for pin control.
+ */
+
+#ifndef _PM_API_IOCTL_H_
+#define _PM_API_IOCTL_H_
+
+#include "pm_common.h"
+
+enum pm_ioctl_id {
+       IOCTL_GET_RPU_OPER_MODE,
+       IOCTL_SET_RPU_OPER_MODE,
+       IOCTL_RPU_BOOT_ADDR_CONFIG,
+       IOCTL_TCM_COMB_CONFIG,
+};
+
+enum rpu_oper_mode {
+       PM_RPU_MODE_LOCKSTEP,
+       PM_RPU_MODE_SPLIT,
+};
+
+enum rpu_boot_mem {
+       PM_RPU_BOOTMEM_LOVEC,
+       PM_RPU_BOOTMEM_HIVEC,
+};
+
+enum rpu_tcm_comb {
+       PM_RPU_TCM_SPLIT,
+       PM_RPU_TCM_COMB,
+};
+
+enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
+                               unsigned int ioctl_id,
+                               unsigned int arg1,
+                               unsigned int arg2,
+                               unsigned int *value);
+#endif /* _PM_API_IOCTL_H_ */
index 14c78fd45edff7c1dc68ffecaaedc5020c81cff4..be243717e4ae314d780e7b771c1413467e2c8b52 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <arch_helpers.h>
 #include <platform.h>
+#include "pm_api_ioctl.h"
 #include "pm_api_pinctrl.h"
 #include "pm_api_sys.h"
 #include "pm_client.h"
@@ -636,3 +637,24 @@ enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
 {
        return pm_api_pinctrl_set_config(pin, param, value);
 }
+
+/**
+ * pm_ioctl() -  PM IOCTL API for device control and configs
+ * @node_id    Node ID of the device
+ * @ioctl_id   ID of the requested IOCTL
+ * @arg1       Argument 1 to requested IOCTL call
+ * @arg2       Argument 2 to requested IOCTL call
+ * @out                Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+                           unsigned int ioctl_id,
+                           unsigned int arg1,
+                           unsigned int arg2,
+                           unsigned int *value)
+{
+       return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
+}
index f240d4915627780c7b605deecf36754aad03f2d4..1c91e8f49f76073be991012de4842944bf1e47f9 100644 (file)
@@ -105,5 +105,10 @@ enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
 enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
                                         unsigned int param,
                                         unsigned int value);
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+                           unsigned int ioctl_id,
+                           unsigned int arg1,
+                           unsigned int arg2,
+                           unsigned int *value);
 
 #endif /* _PM_API_SYS_H_ */
index c9656e31fb7574ea77878805bc21feb76ae055df..afd92f649fee40b64db92eb7409f5d5fa52dbfdb 100644 (file)
@@ -75,6 +75,7 @@ enum pm_api_id {
        PM_PINCTRL_SET_FUNCTION,
        PM_PINCTRL_CONFIG_PARAM_GET,
        PM_PINCTRL_CONFIG_PARAM_SET,
+       PM_IOCTL,
        PM_API_MAX
 };
 
index 22b6bc39f85e846f07ef766c57fcefc39bbd5ee3..648de24bad47e986677ad11c9186afdf03310c55 100644 (file)
@@ -280,6 +280,15 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
                ret = pm_pinctrl_set_config(pm_arg[0], pm_arg[1], pm_arg[2]);
                SMC_RET1(handle, (uint64_t)ret);
 
+       case PM_IOCTL:
+       {
+               uint32_t value;
+
+               ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
+                              pm_arg[3], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+       }
+
        default:
                WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
                SMC_RET1(handle, SMC_UNK);
index 45fa387d6c15c113334e5becf7fd4e40ce7c8343..54036f99bbc6b01a39ea3c87868d83455d4a7b2a 100644 (file)
@@ -47,7 +47,9 @@
 #define CRL_APB_RPLL_CTRL              (CRL_APB_BASE + 0x30)
 #define CRL_APB_BOOT_MODE_USER         (CRL_APB_BASE + 0x200)
 #define CRL_APB_RESET_CTRL             (CRL_APB_BASE + 0x218)
+#define CRL_APB_RST_LPD_TOP            (CRL_APB_BASE + 0x23C)
 
+#define CRL_APB_RPU_AMBA_RESET         (1 << 2)
 #define CRL_APB_RPLL_CTRL_BYPASS       (1 << 3)
 
 #define CRL_APB_RESET_CTRL_SOFT_RESET  (1 << 4)
 
 #define IOU_SLCR_BASEADDR              0xFF180000
 
+#define ZYNQMP_RPU_GLBL_CNTL                   0xFF9A0000
+#define ZYNQMP_RPU0_CFG                                0xFF9A0100
+#define ZYNQMP_RPU1_CFG                                0xFF9A0200
+#define ZYNQMP_SLSPLIT_MASK                    0x08
+#define ZYNQMP_TCM_COMB_MASK                   0x40
+#define ZYNQMP_SLCLAMP_MASK                    0x10
+#define ZYNQMP_VINITHI_MASK                    0x04
+
 #endif /* __ZYNQMP_DEF_H__ */